;info "Written by Jeremy R. Brown (http://www.jeremy-brown.com/) \nbased on the Silence Finder script by\nAlex S. Brown, PMP (http://www.alexsbrown.com) \n\Released under terms of the GNU General Public License version 2\nAdds region labels for areas of sound according to the specified level\nand duration of surrounding silence. If too many labels are produced,\nincrease the silence level and duration; if too few are produced,\nreduce the level and duration."
;control sil-lev "Treat audio below this level as silence [ -dB]" real "" 26 0 100
;control sil-dur "Minimum duration of silence between sounds [seconds]" real "" 1.0 0.1 5.0
;control labelbeforedur "Label starting point [seconds before sound starts]" real "" 0.1 0.0 1.0
;control labelafterdur "Label ending point [seconds after sound ends]" real "" 0.1 0.0 1.0
;control finallabel "Add a label at the end of the track? [No=0, Yes=1]" int "" 0 0 1
;30Dec09: couple of changes made to default control values by Gale Andrews
;Create a function to make the sum the two channels if they are stereo
;Set the silence threshold level (convert it to a linear form)
(setq thres (db-to-linear (* -1 sil-lev)))
;Store the sample rate of the sound
(setq s1-srate (snd-srate (my-s s)))
;Initialize the variable that will hold the length of the sound.
;Do not calculate it now with snd-length, because it would waste memory.
;We will calculate it later.
(setq s1-length 0)
;Initialize the silence counter
(setq sil-c 0)
;Initialize the labels variable
(setq l NIL)
;Convert the silence duration in seconds to a length in samples
(setq sil-length (* sil-dur s1-srate))
;Set the sound-start marker to -1, indicating no sound has been found yet
(setq sound-start -1)
(setq silence-start -1)
;Set the flag that says we are looking for the start of a sound (as opposed to the start of a silence)
(setq sound-search 1)
;Set the counter that counts sounds
(setq sound-count 0)
(setq label-string "")
;Define a function to add new items to the list of labels
(defun add-label (l-starttime l-endtime l-text)
(setq l (cons (list l-starttime l-endtime l-text) l))
)
;The main working part of the program, it counts
;the number of sequential samples with volume under
;the threshold. It adds to a list of markers every time
;there is a longer period of silence than the silence
;duration amount.
;It runs through a loop, adding to the list of markers (l)
;each time it finds silence.
(let (s1) ;Define s1 as a local variable to allow efficient memory use
; Get the sample into s1, then free s to save memory
(setq s1 (my-s s))
(setq s nil)
;Capture the result of this "do" loop, because we need the sound's length
;in samples.
(setq s1-length
;Keep repeating, incrementing the counter and getting another sample
;each time through the loop.
(do ((n 1 (+ n 1)) (v (snd-fetch s1) (setq v (snd-fetch s1))))
;Exit when we run out of samples (v is nil) and return the number of
;samples processed (n)
((not v) n)
;Start the execution part of the do loop
;if found silence, increment the silence counter; if silence-start is not already > -1, set the start of silence to the current sample number (n)
(if (< v thres)
(progn
(setq sil-c (+ sil-c 1))
(if (= silence-start -1) (setq silence-start n))
)
)
;if found sound, and sound-search is 1, mark the start of the sound and change sound-search to 0 (look for silence next)
(if (and (>= v thres) (= sound-search 1))
(progn
(setq sound-search 0)
(setq sound-start n)
(setq sound-count (1+ sound-count))
)
)
;if found silence, and silence-counter is long enough, and sound-search is 0, and sound-start is not -1, and silence-start is not -1, that indicates the end of a sound (for which we have already found the beginning), which we should now label